﻿using HelperFromTheSkeleton.Convert;
using HelperFromTheSkeleton.HttpHelper;
using System.Net.Http;
using System.Security.Cryptography.X509Certificates;
using System.Text.Json.Nodes;

namespace HelperFromTheSkeleton.HttpManage
{
    /// <summary>
    /// Http服务
    /// </summary>
    public class HttpService : IHttpService
    {

        private Http _http;

        public HttpService()
        {
            _http = new Http();
        }
        public HttpService(X509Certificate2[] certificate2s)
        {
            _http = new Http(certificate2s);
        }

        /// <summary>
        /// Post请求
        /// </summary>
        /// <typeparam name="Result">结果类型</typeparam>
        /// <typeparam name="T">请求数据类型</typeparam>
        /// <param name="data">请求数据</param>
        /// <param name="url">请求地址</param>
        /// <returns></returns>
        public async Task<Result?> PostAsync<Result, T>(T data, string url) where Result : class where T : class
        {
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage();
            httpRequestMessage.Method = HttpMethod.Post;
            httpRequestMessage.RequestUri = new Uri(url);
            var modelJson = data.ToJson();
            httpRequestMessage.Content = new StringContent(modelJson);
            httpRequestMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
            var stringResult = await _http.SendAsync(httpRequestMessage);
            var result = stringResult.ToObject<Result>();
            return result;
        }

        /// <summary>
        /// Post请求
        /// </summary>
        /// <typeparam name="Result">结果类型</typeparam>
        /// <typeparam name="T">请求数据类型</typeparam>
        /// <param name="data">请求数据</param>
        /// <param name="url">请求地址</param>
        /// <returns></returns>
        public async Task<string> PostAsync(string data, string url)
        {
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage();
            httpRequestMessage.Method = HttpMethod.Post;
            httpRequestMessage.RequestUri = new Uri(url);
            httpRequestMessage.Content = new StringContent(data);
            httpRequestMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
            var stringResult = await _http.SendAsync(httpRequestMessage);
            return stringResult ?? "";
        }

        /// <summary>
        /// Post请求
        /// </summary>
        /// <typeparam name="Result">结果类型</typeparam>
        /// <typeparam name="T">请求数据类型</typeparam>
        /// <param name="data">请求数据</param>
        /// <param name="url">请求地址</param>
        /// <returns></returns>
        public async Task<JsonObject?> PostAsync<T>(T data, string url) where T : class
        {
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage();
            httpRequestMessage.Method = HttpMethod.Post;
            httpRequestMessage.RequestUri = new Uri(url);
            var modelJson = data.ToJson();
            httpRequestMessage.Content = new StringContent(modelJson);
            httpRequestMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
            var stringResult = await _http.SendAsync(httpRequestMessage);
            var result = JsonNode.Parse(stringResult ?? "")?.AsObject();
            return result;
        }

        /// <summary>
        /// 获取字符串结果的Post请求
        /// </summary>
        /// <typeparam name="Result">结果类型</typeparam>
        /// <typeparam name="T">请求数据类型</typeparam>
        /// <param name="data">请求数据</param>
        /// <param name="url">请求地址</param>
        /// <returns></returns>
        public async Task<string?> PostGetStringResultAsync<T>(T data, string url) where T : class
        {
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage();
            httpRequestMessage.Method = HttpMethod.Post;
            httpRequestMessage.RequestUri = new Uri(url);
            var modelJson = data.ToJson();
            httpRequestMessage.Content = new StringContent(modelJson);
            httpRequestMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
            var stringResult = await _http.SendAsync(httpRequestMessage);
            return stringResult ?? "";
        }

        /// <summary>
        /// Post请求
        /// </summary>
        /// <typeparam name="Result">结果类型</typeparam>
        /// <typeparam name="T">请求数据类型</typeparam>
        /// <param name="heard">额外的头</param>
        /// <param name="data">请求数据</param>
        /// <param name="url">请求地址</param>
        /// <returns></returns>
        public async Task<Result?> PostAsync<Result, T>(Dictionary<string, string> heard, T data, string url) where Result : class where T : class
        {
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage();
            httpRequestMessage.Method = HttpMethod.Post;
            httpRequestMessage.RequestUri = new Uri(url);
            var modelJson = data.ToJson();
            httpRequestMessage.Content = new StringContent(modelJson);
            httpRequestMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
            SetHeaders(ref httpRequestMessage, heard);
            var stringResult = await _http.SendAsync(httpRequestMessage);
            var result = stringResult.ToObject<Result>();
            return result;
        }

        /// <summary>
        ///  Post请求
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="heard"></param>
        /// <param name="data"></param>
        /// <param name="url"></param>
        /// <returns></returns>
        public async Task<JsonObject?> PostAsync<T>(Dictionary<string, string> heard, T data, string url) where T : class
        {
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage();
            httpRequestMessage.Method = HttpMethod.Post;
            httpRequestMessage.RequestUri = new Uri(url);
            var modelJson = data.ToJson();
            httpRequestMessage.Content = new StringContent(modelJson);
            httpRequestMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
            SetHeaders(ref httpRequestMessage, heard);
            var stringResult = await _http.SendAsync(httpRequestMessage);
            var result = JsonNode.Parse(stringResult ?? "")?.AsObject();
            return result;
        }

        /// <summary>
        /// 获取字符串结果的Post请求
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="heard"></param>
        /// <param name="data"></param>
        /// <param name="url"></param>
        /// <returns></returns>
        public async Task<string?> PostGetStringResultAsync<T>(Dictionary<string, string> heard, T data, string url) where T : class
        {
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage();
            httpRequestMessage.Method = HttpMethod.Post;
            httpRequestMessage.RequestUri = new Uri(url);
            var modelJson = data.ToJson();
            httpRequestMessage.Content = new StringContent(modelJson);
            httpRequestMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
            SetHeaders(ref httpRequestMessage, heard);
            var stringResult = await _http.SendAsync(httpRequestMessage);
            return stringResult;
        }

        public async Task<Result?> GetAsync<Result>(Dictionary<string, object> pairs, string url) where Result : class
        {
            if (pairs.Count > 0)
            {
                url = $"{url}?";
                List<string> strings = pairs.Select(m => $"{m.Key}={m.Value}").ToList();
                url = url + string.Join("&", strings);

            }
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage();
            httpRequestMessage.Method = HttpMethod.Get;
            httpRequestMessage.RequestUri = new Uri(url);
            httpRequestMessage.Headers.TryAddWithoutValidation("Content-Type", "application/json");
            var stringResult = await _http.SendAsync(httpRequestMessage);
            var result = stringResult.ToObject<Result>();
            return result;
        }

        public async Task<Result?> GetAsync<Result>(Dictionary<string, string> heard, Dictionary<string, object> pairs, string url) where Result : class
        {
            if (pairs.Count > 0)
            {
                url = $"{url}?";
                List<string> strings = pairs.Select(m => $"{m.Key}={m.Value}").ToList();
                url = url + string.Join("&", strings);

            }
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage();
            httpRequestMessage.Method = HttpMethod.Get;
            httpRequestMessage.RequestUri = new Uri(url);
            httpRequestMessage.Headers.TryAddWithoutValidation("Content-Type", "application/json");
            SetHeaders(ref httpRequestMessage, heard);
            var stringResult = await _http.SendAsync(httpRequestMessage);
            var result = stringResult.ToObject<Result>();
            return result;
        }

        /// <summary>
        /// From提交
        /// </summary>
        /// <typeparam name="Result"></typeparam>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <param name="url"></param>
        /// <returns></returns>
        public async Task<Result?> FromSubmitAsync<Result, T>(T data, string url) where Result : class where T : class
        {
            Dictionary<string, string> dataDic = GetParameterValueDic(data);
            using FormUrlEncodedContent content = new FormUrlEncodedContent(dataDic);
            HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, url);
            requestMessage.Headers.Add("User-Agent", "Daye/1.0");
            requestMessage.Content = content;
            var result = (await _http.SendAsync(requestMessage)).ToObject<Result>();
            return result;
        }

        //根据此文档的代码，实现一个From提交的方法
        public async Task<Result?> PostFormAsync<Result, RequestT>(RequestT requestData, string url) where Result : class where RequestT : class
        {
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage();
            httpRequestMessage.Method = HttpMethod.Post;
            httpRequestMessage.RequestUri = new Uri(url);
            var dic = GetParameterValueDic(requestData);
            var formContent = new FormUrlEncodedContent(dic);
            httpRequestMessage.Content = formContent;
            httpRequestMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-www-form-urlencoded");
            var stringResult = await _http.SendAsync(httpRequestMessage);
            var result = stringResult.ToObject<Result>();
            return result;
        }

        /// <summary>
        /// XAMLPost提交
        /// </summary>
        /// <typeparam name="Result"></typeparam>
        /// <typeparam name="RequestT"></typeparam>
        /// <param name="requestData"></param>
        /// <param name="url"></param>
        /// <returns></returns>
        public async Task<Result?> PostXmlAsync<Result, RequestT>(RequestT requestData, string url) where Result : class where RequestT : class
        {
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage();
            httpRequestMessage.Method = HttpMethod.Post;
            httpRequestMessage.RequestUri = new Uri(url);
            var modelJson = requestData.ToJson().JsonToXml();
            httpRequestMessage.Content = new StringContent(modelJson);
            httpRequestMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/xml");
            var stringResult = await _http.SendAsync(httpRequestMessage);
            var result = stringResult.ToObject<Result>();
            return result;
        }

        /// <summary>
        /// 获取参数与值字典
        /// </summary>
        /// <returns></returns>
        private Dictionary<string, string> GetParameterValueDic<RequestT>(RequestT requestData)
        {
            var requestType = requestData?.GetType();
            var requestFildInfo = requestType?.GetProperties();
            if (requestFildInfo == null) return new Dictionary<string, string>();
            var result = new Dictionary<string, string>();
            foreach (var val in requestFildInfo)
            {
                var value = val.GetValue(requestData)?.ToString() ?? "";
                if (string.IsNullOrWhiteSpace(value)) continue;
                result.Add(val.Name, value);
            }
            return result;
        }

        private void SetHeaders(ref HttpRequestMessage httpRequestMessage, Dictionary<string, string> heard)
        {
            if (heard?.Count > 0)
            {
                foreach (var val in heard)
                {
                    httpRequestMessage.Headers.TryAddWithoutValidation(val.Key, val.Value);
                    httpRequestMessage.Content?.Headers.TryAddWithoutValidation(val.Key, val.Value);
                }
            }
        }
    }


}